﻿//Write a method that calculates the number of workdays between today and given date, passed as parameter.
//Consider that workdays are all days from Monday to Friday except a fixed list of public holidays specified preliminary as array.


using System;

public class NumberOfWorkdays
{
    public static void Main()
    {
        Console.WriteLine("Enter date to calculate number of workdays in format 'day.month.year'");
        Console.Write("Date must be great or equal to {0:dd.MM.yyyy}\nDate = ", DateTime.Now.Date);
        string date = Console.ReadLine();
        string[] array = date.Split('.');
        DateTime newDate = new DateTime(int.Parse(array[2]), int.Parse(array[1]), int.Parse(array[0]));
        TimeSpan days = newDate - DateTime.Now;         
        DateTime dayEaster;
        DateTime[] holidays;
        int workdays = 0;
        if (days.Days < 0)
        {
            Console.WriteLine("Bad input!!!\nYou enter date before {0:dd.MM.yyyy}", DateTime.Now.Date);
        }
        else
        {
            for (int i = 0; i <= newDate.Year - DateTime.Now.Year; i++)
            {
                if (newDate.Year - DateTime.Now.AddYears(i).Year > 0)
                {
                    days = new DateTime(DateTime.Now.Year, 12, 31) - DateTime.Now;
                }
                else
                {
                    days = newDate - new DateTime(DateTime.Now.AddYears(i).Year, 1, 1);
                }
                dayEaster = EasterHolidays(DateTime.Now.AddYears(i).Year);
                holidays = FillHolidaysArray(DateTime.Now.AddYears(i).Year, dayEaster);
                WorkdaysCount(days, holidays, ref workdays);
            }
        }

        Console.WriteLine("Workdays between today and {0:dd.MM.yyyy} is {1}", newDate, workdays);
    }

    private static void WorkdaysCount(TimeSpan days, DateTime[] holidays, ref int workdays)
    {
        for (int i = 1; i <= days.Days; i++)
        {
            if (!(DateTime.Now.AddDays(i).DayOfWeek == DayOfWeek.Saturday ^ DateTime.Now.AddDays(i).DayOfWeek == DayOfWeek.Sunday))
            {
                workdays++;
                for (int j = 0; j < holidays.Length; j++)
                {
                    if (DateTime.Now.AddDays(i).Date == holidays[j])
                    {
                        workdays--;
                        break;
                    }
                }
            }
        }
    }

    private static DateTime[] FillHolidaysArray(int year, DateTime dayEaster)
    {
        DateTime friday = dayEaster.AddDays(-2);
        DateTime saturday = dayEaster.AddDays(-1);
        DateTime monday = dayEaster.AddDays(1);
        DateTime[] holidays = new DateTime[] 
        {
            new DateTime(year, 01, 01),
            new DateTime(year, 03, 03),
            new DateTime(friday.Year, friday.Month, friday.Day),
            new DateTime(saturday.Year, saturday.Month, saturday.Day),
            new DateTime(dayEaster.Year, dayEaster.Month, dayEaster.Day),
            new DateTime(monday.Year, monday.Month, monday.Day),
            new DateTime(year, 05, 01),
            new DateTime(year, 05, 06),
            new DateTime(year, 05, 24),
            new DateTime(year, 09, 06),
            new DateTime(year, 09, 22),
            new DateTime(year, 11, 01),
            new DateTime(year, 12, 24),
            new DateTime(year, 12, 25),
            new DateTime(year, 12, 26),
        };
        Array.Sort(holidays);
        return holidays;
    }

    private static DateTime EasterHolidays(int year)
    {
        int a = year % 19;
        int b = year % 4;
        int c = year % 7;
        int d = (19 * a + 15) % 30;
        int e = (2 * b + 4 * c + 6 * d + 6) % 7;
        int dayEaster = 0;
        int monthEaster = 0;
        //if (d + e) > 10, Easter old style will be (d + e + 4) april, otherwise - (35 + d + e) march
        if (d + e > 10)
        {
            dayEaster = d + e + 4;
            monthEaster = 4;
            if (dayEaster > 30)
            {
                dayEaster -= 30;
                monthEaster++;
            }
        }
        else
        {
            dayEaster = 35 + d + e;
            monthEaster = 3;
            if (dayEaster > 31)
            {
                dayEaster -= 31;
                monthEaster++;
            }
        }
        DateTime easterHolidays = new DateTime(year, monthEaster, dayEaster);
        return easterHolidays;
    }
}